#pragma once

#include "MessageEnd.h"

#include "InteractionFragment.h"
#include "Message.h"

namespace uml {

void MessageEnd::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    PartialElement::fromJson(json, errorList);
    message_ = JsonSerializable::create<Message>(json.value("message"), errorList);

}

void MessageEnd::toJson(QJsonObject& json) {
    PartialElement::toJson(json);
    if (message_) {
        QJsonObject message_json;
        message_->toJson(message_json);
        json.insert("message", message_json);
    }
}

/// <summary>
/// oppositeEnds
    /// This query returns a set including the MessageEnd (if exists) at the opposite
    /// end of the Message for this MessageEnd.
/// </summary>
    /// <code>
    /// result = (message->asSet().messageEnd->asSet()->excluding(self))
    /// </code>
    /// <code>
    /// message->notEmpty()
    /// 
    /// </code>
shared_ptr<vector<MessageEnd>> MessageEnd::oppositeEnds() const
{
    return nullptr;
}

/// <summary>
/// isSend
    /// This query returns value true if this MessageEnd is a sendEvent.
/// </summary>
    /// <code>
    /// message->notEmpty()
    /// 
    /// </code>
    /// <code>
    /// result = (message.sendEvent->asSet()->includes(self))
    /// </code>
bool MessageEnd::isSend() const
{
    return false;
}

/// <summary>
/// isReceive
    /// This query returns value true if this MessageEnd is a receiveEvent.
/// </summary>
    /// <code>
    /// message->notEmpty()
    /// 
    /// </code>
    /// <code>
    /// result = (message.receiveEvent->asSet()->includes(self))
    /// </code>
bool MessageEnd::isReceive() const
{
    return false;
}

/// <summary>
/// enclosingFragments
    /// This query returns a set including the enclosing InteractionFragment this
    /// MessageEnd is enclosed within.
/// </summary>
    /// <code>
    /// result = (if self->select(oclIsKindOf(Gate))->notEmpty() 
    /// then -- it is a Gate
    /// let endGate : Gate = 
    ///   self->select(oclIsKindOf(Gate)).oclAsType(Gate)->asOrderedSet()->first()
    ///   in
    ///   if endGate.isOutsideCF() 
    ///   then endGate.combinedFragment.enclosingInteraction.oclAsType(InteractionFragment)->asSet()->
    ///      union(endGate.combinedFragment.enclosingOperand.oclAsType(InteractionFragment)->asSet())
    ///   else if endGate.isInsideCF() 
    ///     then endGate.combinedFragment.oclAsType(InteractionFragment)->asSet()
    ///     else if endGate.isFormal() 
    ///       then endGate.interaction.oclAsType(InteractionFragment)->asSet()
    ///       else if endGate.isActual() 
    ///         then endGate.interactionUse.enclosingInteraction.oclAsType(InteractionFragment)->asSet()->
    ///      union(endGate.interactionUse.enclosingOperand.oclAsType(InteractionFragment)->asSet())
    ///         else null
    ///         endif
    ///       endif
    ///     endif
    ///   endif
    /// else -- it is a MessageOccurrenceSpecification
    /// let endMOS : MessageOccurrenceSpecification  = 
    ///   self->select(oclIsKindOf(MessageOccurrenceSpecification)).oclAsType(MessageOccurrenceSpecification)->asOrderedSet()->first() 
    ///   in
    ///   if endMOS.enclosingInteraction->notEmpty() 
    ///   then endMOS.enclosingInteraction.oclAsType(InteractionFragment)->asSet()
    ///   else endMOS.enclosingOperand.oclAsType(InteractionFragment)->asSet()
    ///   endif
    /// endif)
    /// </code>
shared_ptr<vector<InteractionFragment>> MessageEnd::enclosingFragments() const
{
    return nullptr;
}

/// <summary>
/// message getter
/// References a Message.
/// </summary>
shared_ptr<Message> MessageEnd::message() const {
    return message_;
}

/// <summary>
/// message setter
/// References a Message.
/// </summary>
void MessageEnd::setMessage(shared_ptr<Message> value) {
    message_ = value;
}

} // namespace uml
